﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace SkypeTranslater
{
	public class GroupCollection : ICollection<Group>
	{
		List<Group> m_groups = null;
		private string m_openedFile = null;

		public GroupCollection()
		{
			m_groups = new List<Group>();
		}

		public string OpenedFile
		{
			get { return m_openedFile; }
		}

		public void Add(Group item)
		{
			if (!m_groups.Contains(item))
				m_groups.Add(item);
		}

		public void Clear()
		{
			m_groups.Clear();
		}

		public bool Contains(Group item)
		{
			return m_groups.Contains(item);
		}

		public void CopyTo(Group[] array, int arrayIndex)
		{
			m_groups.CopyTo(array, arrayIndex);
		}

		public int Count
		{
			get { return m_groups.Count; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public bool Remove(Group item)
		{
			if (m_groups.Contains(item))
				return m_groups.Remove(item);
			return false;
		}

		public bool ContainsByDisplayName(string name)
		{
			return m_groups.Any(x => (string.Compare(x.DisplayName, name, true) == 0 && x.IsTraced));
		}

		/// <summary>
		/// Check for existence in collection
		/// </summary>
		/// <exception cref="System.ArgumentNullException"/>
		/// <param name="name"></param>
		/// <param name="userHandle"></param>
		/// <returns></returns>
		public bool ContainsByDisplayNameOrHandle(string name, string userHandle)
		{
			if (string.IsNullOrEmpty(name))
				throw new ArgumentNullException("name");
			if (string.IsNullOrEmpty(userHandle))
				throw new ArgumentNullException("userHandle");

			return m_groups.Any(x => ((string.Compare(x.DisplayName, name, true) == 0 || string.Compare(x.UserHandle, userHandle, true) == 0) && x.IsTraced));
		}

		public IEnumerator<Group> GetEnumerator()
		{
			return m_groups.GetEnumerator();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			throw new NotImplementedException();
		}


		public void LoadFromXml(string filePath)
		{
			if (string.IsNullOrEmpty(filePath))
				throw new ArgumentNullException(filePath);
			if (!System.IO.File.Exists(filePath))
				throw new System.IO.FileNotFoundException(string.Format("File not found {0}", filePath));

			m_openedFile = filePath;
			m_groups.Clear();

			XDocument doc = XDocument.Load(filePath);

			foreach (XElement element in (from item in doc.Root.Elements("Group") select item))
			{
				Group group = Group.Parse(element);
				if (!this.Contains(group))
					m_groups.Add(group);
			}
		}

		public void SaveToXml(string filePath)
		{
			if (string.IsNullOrEmpty(filePath))
				throw new ArgumentNullException(filePath);
			if (!System.IO.File.Exists(filePath))
				throw new System.IO.FileNotFoundException(string.Format("File not found {0}", filePath));

			XDocument doc = XDocument.Load(filePath);

			doc.Root.RemoveAll();

			foreach (Group item in m_groups)
			{
				doc.Root.Add(item.ConvertToXElement());
			}

			var fi = new System.IO.FileInfo(filePath);
			if (fi.Exists && (fi.Attributes & System.IO.FileAttributes.ReadOnly) != 0)
			{
				fi.Attributes = System.IO.FileAttributes.Normal;
				fi.Delete();
			}

			doc.Save(filePath, SaveOptions.OmitDuplicateNamespaces);
		}

		public List<Group> ImportToList()
		{
			List<Group> list = new List<Group>();
			foreach (Group item in m_groups)
				list.Add(item);

			return list;
		}

		public Group this[int index]
		{
			get { return m_groups[index]; }
		}
	}

	public class Group
	{
		public Group()
		{
			FromLanguage = string.Empty;
			ToLanguage = string.Empty;
			DisplayName = string.Empty;
			UserHandle = string.Empty;
		}

		public string FromLanguage { get; set; }
		public string ToLanguage { get; set; }
		public string DisplayName { get; set; }
		public string UserHandle { get; set; }
		public bool IsTraced { get; set; }

		public override bool Equals(object obj)
		{
			if (obj == null)
				return false;

			if (this.GetType() != obj.GetType())
				return false;

			if (object.ReferenceEquals(this, obj))
				return true;

			Group compared = (Group)obj;
			if (string.Compare(FromLanguage, compared.FromLanguage, false) == 0
				&& string.Compare(ToLanguage, compared.ToLanguage, false) == 0
				&& string.Compare(DisplayName, compared.DisplayName, false) == 0
				&& string.Compare(UserHandle, compared.UserHandle, false) == 0
				&& IsTraced.Equals(compared.IsTraced))
				return true;
			return false;
		}

		public static Group Parse(XElement element)
		{
			Group group = new Group();
			group.DisplayName = element.Element("DisplayName").Value;
			group.FromLanguage = element.Element("FromLanguage").Value;
			group.ToLanguage = element.Element("ToLanguage").Value;
			group.UserHandle = element.Element("UserHandle").Value;
			group.IsTraced = string.Compare(element.Element("IsTraced").Value, "true", true) == 0;
			return group;
		}

		public XElement ConvertToXElement()
		{
			XElement element = new XElement("Group",
				new XElement("FromLanguage", FromLanguage),
				new XElement("ToLanguage", ToLanguage),
				new XElement("DisplayName", DisplayName),
				new XElement("UserHandle", UserHandle),
				new XElement("IsTraced", IsTraced));
			return element;
		}

		public override string ToString()
		{
			return string.Format("{0} - {1} - {2} - {3}", FromLanguage, ToLanguage, DisplayName, IsTraced);
		}

		public override int GetHashCode()
		{
			return UserHandle.Length + this.ToLanguage.Length + this.FromLanguage.Length + this.DisplayName.Length;
		}
	}
}
